home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / BufferedInputStream.java < prev    next >
Text File  |  1998-09-22  |  12KB  |  325 lines

  1. /*
  2.  * @(#)BufferedInputStream.java    1.27 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.io;
  16.  
  17. /**
  18.  * The class implements a buffered input stream. By setting up such 
  19.  * an input stream, an application can read bytes from a stream 
  20.  * without necessarily causing a call to the underlying system for 
  21.  * each byte read. The data is read by blocks into a buffer; 
  22.  * subsequent reads can access the data directly from the buffer. 
  23.  *
  24.  * @author  Arthur van Hoff
  25.  * @version 1.27, 07/01/98
  26.  * @since   JDK1.0
  27.  */
  28. public
  29. class BufferedInputStream extends FilterInputStream {
  30.     /**
  31.      * The buffer where data is stored. 
  32.      *
  33.      * @since   JDK1.0
  34.      */
  35.     protected byte buf[];
  36.  
  37.     /**
  38.      * The index one greater than the index of the last valid byte in 
  39.      * the buffer. 
  40.      *
  41.      * @since   JDK1.0
  42.      */
  43.     protected int count;
  44.  
  45.     /**
  46.      * The current position in the buffer. This is the index of the next 
  47.      * character to be read from the <code>buf</code> array. 
  48.      *
  49.      * @see     java.io.BufferedInputStream#buf
  50.      * @since   JDK1.0
  51.      */
  52.     protected int pos;
  53.     
  54.     /**
  55.      * The value of the <code>pos</code> field at the time the last 
  56.      * <code>mark</code> method was called. The value of this field is 
  57.      * <code>-1</code> if there is no current mark. 
  58.      *
  59.      * @see     java.io.BufferedInputStream#mark(int)
  60.      * @see     java.io.BufferedInputStream#pos
  61.      * @since   JDK1.0
  62.      */
  63.     protected int markpos = -1;
  64.  
  65.     /**
  66.      * The maximum read ahead allowed after a call to the 
  67.      * <code>mark</code> method before subsequent calls to the 
  68.      * <code>reset</code> method fail. 
  69.      *
  70.      * @see     java.io.BufferedInputStream#mark(int)
  71.      * @see     java.io.BufferedInputStream#reset()
  72.      * @since   JDK1.0
  73.      */
  74.     protected int marklimit;
  75.  
  76.     /**
  77.      * Creates a new buffered input stream to read data from the 
  78.      * specified input stream with a default 512-byte buffer size. 
  79.      *
  80.      * @param   in   the underlying input stream.
  81.      * @since   JDK1.0
  82.      */
  83.     public BufferedInputStream(InputStream in) {
  84.     this(in, 2048);
  85.     }
  86.  
  87.     /**
  88.      * Creates a new buffered input stream to read data from the 
  89.      * specified input stream with the specified buffer size. 
  90.      *
  91.      * @param   in     the underlying input stream.
  92.      * @param   size   the buffer size.
  93.      * @since   JDK1.0
  94.      */
  95.     public BufferedInputStream(InputStream in, int size) {
  96.     super(in);
  97.     buf = new byte[size];
  98.     }
  99.  
  100.     /**
  101.      * Fills the buffer with more data, taking into account
  102.      * shuffling and other tricks for dealing with marks.
  103.      * Assumes that it is being called by a synchronized method.
  104.      * This method also assumes that all data has already been read in,
  105.      * hence pos > count.
  106.      */
  107.     private void fill() throws IOException {
  108.     if (markpos < 0)
  109.         pos = 0;        /* no mark: throw away the buffer */
  110.     else if (pos >= buf.length)    /* no room left in buffer */
  111.         if (markpos > 0) {    /* can throw away early part of the buffer */
  112.         int sz = pos - markpos;
  113.         System.arraycopy(buf, markpos, buf, 0, sz);
  114.         pos = sz;
  115.         markpos = 0;
  116.         } else if (buf.length >= marklimit) {
  117.         markpos = -1;    /* buffer got too big, invalidate mark */
  118.         pos = 0;    /* drop buffer contents */
  119.         } else {        /* grow buffer */
  120.         int nsz = pos * 2;
  121.         if (nsz > marklimit)
  122.             nsz = marklimit;
  123.         byte nbuf[] = new byte[nsz];
  124.         System.arraycopy(buf, 0, nbuf, 0, pos);
  125.         buf = nbuf;
  126.         }
  127.     int n = in.read(buf, pos, buf.length - pos);
  128.     count = n <= 0 ? pos : n + pos;
  129.     }
  130.  
  131.     /**
  132.      * Reads the next byte of data from this buffered input stream. The 
  133.      * value byte is returned as an <code>int</code> in the range 
  134.      * <code>0</code> to <code>255</code>. If no byte is available 
  135.      * because the end of the stream has been reached, the value 
  136.      * <code>-1</code> is returned. This method blocks until input data 
  137.      * is available, the end of the stream is detected, or an exception 
  138.      * is thrown. 
  139.      * <p>
  140.      * The <code>read</code> method of <code>BufferedInputStream</code> 
  141.      * returns the next byte of data from its buffer if the buffer is not 
  142.      * empty. Otherwise, it refills the buffer from the underlying input 
  143.      * stream and returns the next character, if the underlying stream 
  144.      * has not returned an end-of-stream indicator. 
  145.      *
  146.      * @return     the next byte of data, or <code>-1</code> if the end of the
  147.      *             stream is reached.
  148.      * @exception  IOException  if an I/O error occurs.
  149.      * @see        java.io.FilterInputStream#in
  150.      * @since      JDK1.0
  151.      */
  152.     public synchronized int read() throws IOException {
  153.     if (pos >= count) {
  154.         fill();
  155.         if (pos >= count)
  156.         return -1;
  157.     }
  158.     return buf[pos++] & 0xff;
  159.     }
  160.  
  161.     /**
  162.      * Reads bytes into a portion of an array.  This method will block until
  163.      * some input is available, an I/O error occurs, or the end of the stream
  164.      * is reached.
  165.      *
  166.      * <p> If this stream's buffer is not empty, bytes are copied from it into
  167.      * the array argument.  Otherwise, the buffer is refilled from the
  168.      * underlying input stream and, unless the stream returns an end-of-stream
  169.      * indication, the array argument is filled with characters from the
  170.      * newly-filled buffer.
  171.      *
  172.      * <p> As an optimization, if the buffer is empty, the mark is not valid,
  173.      * and <code>len</code> is at least as large as the buffer, then this
  174.      * method will read directly from the underlying stream into the given
  175.      * array.  Thus redundant <code>BufferedInputStream</code>s will not copy
  176.      * data unnecessarily.
  177.      *
  178.      * @param      b     destination buffer.
  179.      * @param      off   offset at which to start storing bytes.
  180.      * @param      len   maximum number of bytes to read.
  181.      * @return     the number of bytes read, or <code>-1</code> if the end of
  182.      *             the stream has been reached.
  183.      * @exception  IOException  if an I/O error occurs.
  184.      */
  185.     public synchronized int read(byte b[], int off, int len) throws IOException {
  186.     int avail = count - pos;
  187.     if (avail <= 0) {
  188.         /* If the requested length is larger than the buffer, and if there
  189.            is no mark/reset activity, do not bother to copy the bytes into
  190.            the local buffer.  In this way buffered streams will cascade
  191.            harmlessly. */
  192.         if (len >= buf.length && markpos < 0) {
  193.         return in.read(b, off, len);
  194.         }
  195.         fill();
  196.         avail = count - pos;
  197.         if (avail <= 0)
  198.         return -1;
  199.     }
  200.     int cnt = (avail < len) ? avail : len;
  201.     System.arraycopy(buf, pos, b, off, cnt);
  202.     pos += cnt;
  203.     return cnt;
  204.     }
  205.  
  206.     /**
  207.      * Skips over and discards <code>n</code> bytes of data from the 
  208.      * input stream. The <code>skip</code> method may, for a variety of 
  209.      * reasons, end up skipping over some smaller number of bytes, 
  210.      * possibly zero. The actual number of bytes skipped is returned. 
  211.      * <p>
  212.      * The <code>skip</code> method of <code>BufferedInputStream</code> 
  213.      * compares the number of bytes it has available in its buffer, 
  214.      * <i>k</i>, where <i>k</i> = <code>count - pos</code>, 
  215.      * with <code>n</code>. If <code>n</code> ≤ <i>k</i>, 
  216.      * then the <code>pos</code> field is incremented by <code>n</code>. 
  217.      * Otherwise, the <code>pos</code> field is incremented to have the 
  218.      * value <code>count</code>, and the remaining bytes are skipped by 
  219.      * calling the <code>skip</code> method on the underlying input 
  220.      * stream, supplying the argument <code>n -</code> <i>k</i>. 
  221.      *
  222.      * @param      n   the number of bytes to be skipped.
  223.      * @return     the actual number of bytes skipped.
  224.      * @exception  IOException  if an I/O error occurs.
  225.      * @since      JDK1.0
  226.      */
  227.     public synchronized long skip(long n) throws IOException {
  228.     if (n < 0) {
  229.         return 0;
  230.     }
  231.     long avail = count - pos;
  232.  
  233.     if (avail >= n) {
  234.         pos += n;
  235.         return n;
  236.     }
  237.  
  238.     pos += avail;
  239.     return avail + in.skip(n - avail);
  240.     }
  241.  
  242.     /**
  243.      * Returns the number of bytes that can be read from this input 
  244.      * stream without blocking. 
  245.      * <p>
  246.      * The <code>available</code> method of 
  247.      * <code>BufferedInputStream</code> returns the sum of the the number 
  248.      * of bytes remaining to be read in the buffer 
  249.      * (<code>count - pos</code>) 
  250.      * and the result of calling the <code>available</code> method of the 
  251.      * underlying input stream. 
  252.      *
  253.      * @return     the number of bytes that can be read from this input
  254.      *             stream without blocking.
  255.      * @exception  IOException  if an I/O error occurs.
  256.      * @see        java.io.FilterInputStream#in
  257.      * @since      JDK1.0
  258.      */
  259.     public synchronized int available() throws IOException {
  260.     return (count - pos) + in.available();
  261.     }
  262.  
  263.     /**
  264.      * Marks the current position in this input stream. A subsequent 
  265.      * call to the <code>reset</code> method repositions the stream at 
  266.      * the last marked position so that subsequent reads re-read the same 
  267.      * bytes. 
  268.      * <p>
  269.      * The <code>readlimit</code> argument tells the input stream to 
  270.      * allow that many bytes to be read before the mark position gets 
  271.      * invalidated. 
  272.      *
  273.      * @param   readlimit   the maximum limit of bytes that can be read before
  274.      *                      the mark position becomes invalid.
  275.      * @see     java.io.BufferedInputStream#reset()
  276.      * @since   JDK1.0
  277.      */
  278.     public synchronized void mark(int readlimit) {
  279.     marklimit = readlimit;
  280.     markpos = pos;
  281.     }
  282.  
  283.     /**
  284.      * Repositions this stream to the position at the time the 
  285.      * <code>mark</code> method was last called on this input stream. 
  286.      * <p>
  287.      * If the stream has not been marked, or if the mark has been invalidated,
  288.      * an IOException is thrown. Stream marks are intended to be used in
  289.      * situations where you need to read ahead a little to see what's in
  290.      * the stream. Often this is most easily done by invoking some
  291.      * general parser. If the stream is of the type handled by the
  292.      * parser, it just chugs along happily. If the stream is not of
  293.      * that type, the parser should toss an exception when it fails. If an
  294.      * exception gets tossed within readlimit bytes, the parser will allow the
  295.      * outer code to reset the stream and to try another parser.
  296.      *
  297.      * @exception  IOException  if this stream has not been marked or
  298.      *               if the mark has been invalidated.
  299.      * @see        java.io.BufferedInputStream#mark(int)
  300.      * @since      JDK1.0
  301.      */
  302.     public synchronized void reset() throws IOException {
  303.     if (markpos < 0)
  304.         throw new IOException("Resetting to invalid mark");
  305.     pos = markpos;
  306.     }
  307.  
  308.     /**
  309.      * Tests if this input stream supports the <code>mark</code> 
  310.      * and <code>reset</code> methods. The <code>markSupported</code> 
  311.      * method of <code>BufferedInputStream</code> returns 
  312.      * <code>true</code>. 
  313.      *
  314.      * @return  a <code>boolean</code> indicating if this stream type supports
  315.      *          the <code>mark</code> and <code>reset</code> methods.
  316.      * @see     java.io.InputStream#mark(int)
  317.      * @see     java.io.InputStream#reset()
  318.      * @since   JDK1.0
  319.  
  320.      */
  321.     public boolean markSupported() {
  322.     return true;
  323.     }
  324. }
  325.